์น์ฌ์ดํธ ์ฑ๋ฅ๊ณผ ์ฌ์ฉ์ ๊ฒฝํ ํฅ์์ ์ํ ์๋ฐ์คํฌ๋ฆฝํธ ๋ฒ๋ค ์ต์ ํ ๊ณ ๊ธ ์ฝ๋ ๋ถํ ๊ธฐ๋ฒ์ ์ฌ์ธต์ ์ผ๋ก ๋ค๋ฃน๋๋ค.
์๋ฐ์คํฌ๋ฆฝํธ ๋ฒ๋ค ์ต์ ํ ์ ๋ต: ๊ณ ๊ธ ์ฝ๋ ๋ถํ ๊ธฐ๋ฒ
์ค๋๋ ์ ์น ๊ฐ๋ฐ ํ๊ฒฝ์์ ๋น ๋ฅด๊ณ ๋ฐ์์ฑ์ด ๋ฐ์ด๋ ์ฌ์ฉ์ ๊ฒฝํ์ ์ ๊ณตํ๋ ๊ฒ์ ๋งค์ฐ ์ค์ํฉ๋๋ค. ๋์ฉ๋ ์๋ฐ์คํฌ๋ฆฝํธ ๋ฒ๋ค์ ์น์ฌ์ดํธ ๋ก๋ฉ ์๊ฐ์ ํฐ ์ํฅ์ ๋ฏธ์ณ ์ฌ์ฉ์ ๋ถ๋ง์ ์ ๋ฐํ๊ณ ๋น์ฆ๋์ค ์งํ์๋ ์ํฅ์ ์ค ์ ์์ต๋๋ค. ์ฝ๋ ๋ถํ (Code splitting)์ ์ ํ๋ฆฌ์ผ์ด์ ์ฝ๋๋ฅผ ๋ ์๊ณ ๊ด๋ฆฌํ๊ธฐ ์ฌ์ด ์ฒญํฌ(chunk)๋ก ๋๋์ด ํ์ํ ๋ ๋ก๋ํ ์ ์๊ฒ ํ๋ ๊ฐ๋ ฅํ ํด๊ฒฐ์ฑ ์ ๋๋ค.
์ด ํฌ๊ด์ ์ธ ๊ฐ์ด๋์์๋ ๊ณ ๊ธ ์ฝ๋ ๋ถํ ๊ธฐ๋ฒ์ ์ฌ์ธต์ ์ผ๋ก ๋ค๋ฃจ๋ฉฐ, ์๋ฐ์คํฌ๋ฆฝํธ ๋ฒ๋ค์ ์ต์ ํํ๊ณ ์น์ฌ์ดํธ ์ฑ๋ฅ์ ํฅ์์ํค๊ธฐ ์ํ ๋ค์ํ ์ ๋ต๊ณผ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ์ดํด๋ด ๋๋ค. Webpack, Rollup, Parcel๊ณผ ๊ฐ์ ๋ค์ํ ๋ฒ๋ค๋ฌ์ ์ ์ฉ ๊ฐ๋ฅํ ๊ฐ๋ ์ ๋ค๋ฃจ๊ณ ๋ชจ๋ ์์ค์ ๊ฐ๋ฐ์์๊ฒ ์ค์ฉ์ ์ธ ํต์ฐฐ๋ ฅ์ ์ ๊ณตํ ๊ฒ์ ๋๋ค.
์ฝ๋ ๋ถํ ์ด๋ ๋ฌด์์ธ๊ฐ?
์ฝ๋ ๋ถํ ์ ํ๋์ ํฐ ์๋ฐ์คํฌ๋ฆฝํธ ๋ฒ๋ค์ ๋ ์๊ณ ๋ ๋ฆฝ์ ์ธ ์ฌ๋ฌ ๊ฐ์ ์ฒญํฌ๋ก ๋๋๋ ๊ดํ์ ๋๋ค. ์ ์ฒด ์ ํ๋ฆฌ์ผ์ด์ ์ฝ๋๋ฅผ ํ ๋ฒ์ ๋ก๋ํ๋ ๋์ , ํ์ํ ๋ ํ์ํ ์ฝ๋๋ง ๋ค์ด๋ก๋ํฉ๋๋ค. ์ด ์ ๊ทผ ๋ฐฉ์์ ์ฌ๋ฌ ๊ฐ์ง ์ด์ ์ ์ ๊ณตํฉ๋๋ค:
- ์ด๊ธฐ ๋ก๋ฉ ์๊ฐ ๊ฐ์ : ์ด๊ธฐ ํ์ด์ง ๋ก๋ ์ ๋ค์ด๋ก๋ํ๊ณ ํ์ฑํด์ผ ํ๋ ์๋ฐ์คํฌ๋ฆฝํธ์ ์์ ์ค์ฌ ์ฒด๊ฐ ์ฑ๋ฅ์ ํฅ์์ํต๋๋ค.
- ์ฌ์ฉ์ ๊ฒฝํ ํฅ์: ๋ ๋น ๋ฅธ ๋ก๋ฉ ์๊ฐ์ ๋ ๋ฐ์์ ์ด๊ณ ์ฆ๊ฑฐ์ด ์ฌ์ฉ์ ๊ฒฝํ์ผ๋ก ์ด์ด์ง๋๋ค.
- ๋ ๋์ ์บ์ฑ: ์์ ๋ฒ๋ค์ ๋ ํจ๊ณผ์ ์ผ๋ก ์บ์๋ ์ ์์ด, ์ฌ๋ฐฉ๋ฌธ ์ ์ฝ๋๋ฅผ ๋ค์ ๋ค์ด๋ก๋ํ ํ์์ฑ์ ์ค์ฌ์ค๋๋ค.
- ๋์ญํญ ์๋น ๊ฐ์: ์ฌ์ฉ์๋ ํ์ํ ์ฝ๋๋ง ๋ค์ด๋ก๋ํ๋ฏ๋ก ๋์ญํญ์ ์ ์ฝํ๊ณ ๋ฐ์ดํฐ ์๊ธ์ ์ค์ผ ์ ์์ผ๋ฉฐ, ํนํ ์ธํฐ๋ท ์ ์์ด ์ ํ๋ ์ง์ญ์ ์ฌ์ฉ์์๊ฒ ์ ์ฉํฉ๋๋ค.
์ฝ๋ ๋ถํ ์ ์ ํ
์ฝ๋ ๋ถํ ์๋ ์ฃผ๋ก ๋ ๊ฐ์ง ์ฃผ์ ์ ๊ทผ ๋ฐฉ์์ด ์์ต๋๋ค:
1. ์ง์ ์ ๋ถํ (Entry Point Splitting)
์ง์ ์ ๋ถํ ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฌ๋ฌ ๋ค๋ฅธ ์ง์ ์ (entry point)์ ๋ํด ๋ณ๋์ ๋ฒ๋ค์ ์์ฑํ๋ ๊ฒ์ ํฌํจํฉ๋๋ค. ๊ฐ ์ง์ ์ ์ ๊ณ ์ ํ ๊ธฐ๋ฅ์ด๋ ํ์ด์ง๋ฅผ ๋ํ๋ ๋๋ค. ์๋ฅผ ๋ค์ด, ์ ์ ์๊ฑฐ๋ ์น์ฌ์ดํธ๋ ํํ์ด์ง, ์ํ ๋ชฉ๋ก ํ์ด์ง, ๊ฒฐ์ ํ์ด์ง์ ๋ํด ๋ณ๋์ ์ง์ ์ ์ ๊ฐ์ง ์ ์์ต๋๋ค.
์์:
`index.js`์ `about.js`๋ผ๋ ๋ ๊ฐ์ ์ง์ ์ ์ด ์๋ ์น์ฌ์ดํธ๋ฅผ ๊ฐ์ ํด ๋ด ์๋ค. Webpack์ ์ฌ์ฉํ์ฌ `webpack.config.js` ํ์ผ์์ ์ฌ๋ฌ ์ง์ ์ ์ ๊ตฌ์ฑํ ์ ์์ต๋๋ค:
module.exports = {
entry: {
index: './src/index.js',
about: './src/about.js'
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
์ด ๊ตฌ์ฑ์ `index.bundle.js`์ `about.bundle.js`๋ผ๋ ๋ ๊ฐ์ ๊ฐ๋ณ ๋ฒ๋ค์ ์์ฑํฉ๋๋ค. ๋ธ๋ผ์ฐ์ ๋ ์ ์ ์ค์ธ ํ์ด์ง์ ํด๋นํ๋ ๋ฒ๋ค๋ง ๋ค์ด๋ก๋ํ๊ฒ ๋ฉ๋๋ค.
2. ๋์ ์ํฌํธ (Dynamic Imports) (๋ผ์ฐํธ ๊ธฐ๋ฐ ๋๋ ์ปดํฌ๋ํธ ๊ธฐ๋ฐ ๋ถํ )
๋์ ์ํฌํธ๋ฅผ ์ฌ์ฉํ๋ฉด ์ฌ์ฉ์๊ฐ ํน์ ๊ธฐ๋ฅ๊ณผ ์ํธ ์์ฉํ๊ฑฐ๋ ํน์ ๋ผ์ฐํธ๋ก ์ด๋ํ ๋์ ๊ฐ์ด ํ์์ ๋ฐ๋ผ ์๋ฐ์คํฌ๋ฆฝํธ ๋ชจ๋์ ๋ก๋ํ ์ ์์ต๋๋ค. ์ด ์ ๊ทผ ๋ฐฉ์์ ์ฝ๋ ๋ก๋ฉ์ ๋ํ ๋ ์ธ๋ฐํ ์ ์ด๋ฅผ ์ ๊ณตํ๋ฉฐ, ํนํ ํฌ๊ณ ๋ณต์กํ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฑ๋ฅ์ ํฌ๊ฒ ํฅ์์ํฌ ์ ์์ต๋๋ค.
์์:
React ์ ํ๋ฆฌ์ผ์ด์ ์์ ๋ผ์ฐํธ ๊ธฐ๋ฐ ์ฝ๋ ๋ถํ ์ ์ํด ๋์ ์ํฌํธ๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ:
import React, { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
const Home = lazy(() => import('./pages/Home'));
const About = lazy(() => import('./pages/About'));
const Products = lazy(() => import('./pages/Products'));
function App() {
return (
๋ก๋ฉ ์ค... ์ด ์์ ์์ `Home`, `About`, `Products` ์ปดํฌ๋ํธ๋ `React.lazy()`๋ฅผ ์ฌ์ฉํ์ฌ ๋์ ์ผ๋ก ๋ก๋๋ฉ๋๋ค. `Suspense` ์ปดํฌ๋ํธ๋ ์ปดํฌ๋ํธ๊ฐ ๋ก๋๋๋ ๋์ ๋์ฒด UI(๋ก๋ฉ ํ์๊ธฐ)๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ด๋ ์ฌ์ฉ์๊ฐ ์ฝ๋๊ฐ ๋ค์ด๋ก๋๋๊ธฐ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ๋์ ๋น ํ๋ฉด์ ๋ณด์ง ์๋๋ก ๋ณด์ฅํฉ๋๋ค. ์ด์ ์ด ํ์ด์ง๋ค์ ๋ณ๋์ ์ฒญํฌ๋ก ๋ถํ ๋์ด ํด๋น ๋ผ์ฐํธ๋ก ์ด๋ํ ๋๋ง ๋ก๋๋ฉ๋๋ค.
๊ณ ๊ธ ์ฝ๋ ๋ถํ ๊ธฐ๋ฒ
๊ธฐ๋ณธ์ ์ธ ์ฝ๋ ๋ถํ ์ ํ ์ธ์๋, ์๋ฐ์คํฌ๋ฆฝํธ ๋ฒ๋ค์ ๋์ฑ ์ต์ ํํ ์ ์๋ ์ฌ๋ฌ ๊ณ ๊ธ ๊ธฐ๋ฒ์ด ์์ต๋๋ค.
1. ๋ฒค๋ ๋ถํ (Vendor Splitting)
๋ฒค๋ ๋ถํ ์ ์๋ํํฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(์: React, Angular, Vue.js)๋ฅผ ๋ณ๋์ ๋ฒ๋ค๋ก ๋ถ๋ฆฌํ๋ ๊ฒ์ ํฌํจํฉ๋๋ค. ์ด๋ฌํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ฝ๋์ ๋นํด ์์ฃผ ๋ณ๊ฒฝ๋ ๊ฐ๋ฅ์ฑ์ด ๋ฎ๊ธฐ ๋๋ฌธ์ ๋ธ๋ผ์ฐ์ ์์ ๋ ํจ๊ณผ์ ์ผ๋ก ์บ์๋ ์ ์์ต๋๋ค.
์์ (Webpack):
module.exports = {
// ... ๋ค๋ฅธ ์ค์ ๋ค
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all'
}
}
}
}
};
์ด Webpack ์ค์ ์ `node_modules` ๋๋ ํ ๋ฆฌ์ ๋ชจ๋ ์ฝ๋๋ฅผ ํฌํจํ๋ `vendors.bundle.js`๋ผ๋ ๋ณ๋์ ๋ฒ๋ค์ ์์ฑํฉ๋๋ค.
2. ๊ณตํต ์ฒญํฌ ์ถ์ถ (Common Chunk Extraction)
๊ณตํต ์ฒญํฌ ์ถ์ถ์ ์ฌ๋ฌ ๋ฒ๋ค ๊ฐ์ ๊ณต์ ๋๋ ์ฝ๋๋ฅผ ์๋ณํ๊ณ ๊ณต์ ์ฝ๋๋ฅผ ํฌํจํ๋ ๋ณ๋์ ๋ฒ๋ค์ ์์ฑํฉ๋๋ค. ์ด๋ ์ค๋ณต์ ์ค์ด๊ณ ์บ์ฑ ํจ์จ์ฑ์ ํฅ์์ํต๋๋ค.
์์ (Webpack):
module.exports = {
// ... ๋ค๋ฅธ ์ค์ ๋ค
optimization: {
splitChunks: {
chunks: 'all',
minSize: 20000, // ์ฒญํฌ ์์ฑ์ ์ํ ์ต์ ํฌ๊ธฐ (๋ฐ์ดํธ ๋จ์).
maxAsyncRequests: 30, // ์จ๋๋งจ๋ ๋ก๋ฉ ์ ์ต๋ ๋ณ๋ ฌ ์์ฒญ ์.
maxInitialRequests: 30, // ์ง์
์ (entry point)์์์ ์ต๋ ๋ณ๋ ฌ ์์ฒญ ์.
automaticNameDelimiter: '~',
cacheGroups: {
defaultVendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2, // ๋ชจ๋์ ๋ถํ ํ๊ธฐ ์ ์ ๊ณต์ ํด์ผ ํ๋ ์ต์ ์ฒญํฌ ์.
priority: -20,
reuseExistingChunk: true
}
}
}
}
};
์ด ์ค์ ์ ์ง์ ๋ ๊ธฐ์ค(์: `minChunks`, `minSize`)์ ๋ฐ๋ผ ๊ณตํต ์ฒญํฌ๋ฅผ ์๋์ผ๋ก ์ถ์ถํฉ๋๋ค.
3. ๋ผ์ฐํธ ํ๋ฆฌํ์นญ ๋ฐ ํ๋ฆฌ๋ก๋ฉ (Route Prefetching and Preloading)
ํ๋ฆฌํ์นญ๊ณผ ํ๋ฆฌ๋ก๋ฉ์ ์ฌ์ฉ์์ ๋ฏธ๋ ํ๋์ ์์ธกํ์ฌ ๋ฆฌ์์ค๋ฅผ ๋ฏธ๋ฆฌ ๋ก๋ํ๋ ๊ธฐ๋ฒ์ ๋๋ค. ํ๋ฆฌํ์นญ์ ๋ธ๋ผ์ฐ์ ๊ฐ ์ ํด ์ํ์ผ ๋ ๋ฐฑ๊ทธ๋ผ์ด๋์์ ๋ฆฌ์์ค๋ฅผ ๋ค์ด๋ก๋ํ๋ ๋ฐ๋ฉด, ํ๋ฆฌ๋ก๋ฉ์ ํ์ฌ ํ์ด์ง์ ํ์์ ์ธ ํน์ ๋ฆฌ์์ค์ ๋ก๋ฉ ์ฐ์ ์์๋ฅผ ๋์ ๋๋ค.
ํ๋ฆฌํ์นญ ์์:
์ด HTML ํ๊ทธ๋ ๋ธ๋ผ์ฐ์ ๊ฐ ์ ํด ์ํ์ผ ๋ `about.bundle.js` ํ์ผ์ ๋ฏธ๋ฆฌ ๊ฐ์ ธ์ค๋๋ก ์ง์ํฉ๋๋ค. ์ด๋ About ํ์ด์ง๋ก์ ํ์ ์๋๋ฅผ ํฌ๊ฒ ๋์ผ ์ ์์ต๋๋ค.
ํ๋ฆฌ๋ก๋ฉ ์์:
์ด HTML ํ๊ทธ๋ ๋ธ๋ผ์ฐ์ ์๊ฒ `critical.bundle.js`์ ๋ก๋ฉ ์ฐ์ ์์๋ฅผ ๋์ด๋๋ก ์ง์ํฉ๋๋ค. ์ด๋ ํ์ด์ง์ ์ด๊ธฐ ๋ ๋๋ง์ ํ์์ ์ธ ์ฝ๋๋ฅผ ๋ก๋ํ๋ ๋ฐ ์ ์ฉํฉ๋๋ค.
4. ํธ๋ฆฌ ์์ดํน (Tree Shaking)
ํธ๋ฆฌ ์์ดํน์ ์๋ฐ์คํฌ๋ฆฝํธ ๋ฒ๋ค์์ ์ฃฝ์ ์ฝ๋(dead code)๋ฅผ ์ ๊ฑฐํ๋ ๊ธฐ๋ฒ์ ๋๋ค. ์ฌ์ฉ๋์ง ์๋ ํจ์, ๋ณ์, ๋ชจ๋์ ์๋ณํ๊ณ ์ ๊ฑฐํ์ฌ ๋ฒ๋ค ํฌ๊ธฐ๋ฅผ ์ค์ ๋๋ค. Webpack ๋ฐ Rollup๊ณผ ๊ฐ์ ๋ฒ๋ค๋ฌ๋ ๊ธฐ๋ณธ์ ์ผ๋ก ํธ๋ฆฌ ์์ดํน์ ์ง์ํฉ๋๋ค.
ํธ๋ฆฌ ์์ดํน์ ์ํ ์ฃผ์ ๊ณ ๋ ค์ฌํญ:
- ES ๋ชจ๋(ESM) ์ฌ์ฉ: ํธ๋ฆฌ ์์ดํน์ ES ๋ชจ๋์ ์ ์ ๊ตฌ์กฐ(`import` ๋ฐ `export` ๋ฌธ ์ฌ์ฉ)์ ์์กดํ์ฌ ์ด๋ค ์ฝ๋๊ฐ ์ฌ์ฉ๋์ง ์๋์ง ํ๋จํฉ๋๋ค.
- ๋ถ์ ํจ๊ณผ(Side Effects) ๋ฐฉ์ง: ๋ถ์ ํจ๊ณผ๋ ํจ์์ ๋ฒ์๋ฅผ ๋ฒ์ด๋ ๋์์ ์ํํ๋ ์ฝ๋(์: ์ ์ญ ๋ณ์ ์์ )์ ๋๋ค. ๋ฒ๋ค๋ฌ๋ ๋ถ์ ํจ๊ณผ๊ฐ ์๋ ์ฝ๋๋ฅผ ํธ๋ฆฌ ์์ดํนํ๊ธฐ ์ด๋ ค์ธ ์ ์์ต๋๋ค.
- `package.json`์ `sideEffects` ์์ฑ ์ฌ์ฉ: `package.json` ํ์ผ์ `sideEffects` ์์ฑ์ ์ฌ์ฉํ์ฌ ํจํค์ง ๋ด ์ด๋ค ํ์ผ์ ๋ถ์ ํจ๊ณผ๊ฐ ์๋์ง ๋ช ์์ ์ผ๋ก ์ ์ธํ ์ ์์ต๋๋ค. ์ด๋ ๋ฒ๋ค๋ฌ๊ฐ ํธ๋ฆฌ ์์ดํน์ ์ต์ ํํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
5. ๊ณ์ฐ ์ง์ฝ์ ์์ ์ ์ํ ์น ์์ปค(Web Workers) ์ฌ์ฉ
์น ์์ปค๋ฅผ ์ฌ์ฉํ๋ฉด ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๋ฅผ ๋ฐฑ๊ทธ๋ผ์ด๋ ์ค๋ ๋์์ ์คํํ์ฌ ๋ฉ์ธ ์ค๋ ๋๊ฐ ์ฐจ๋จ๋๋ ๊ฒ์ ๋ฐฉ์งํ ์ ์์ต๋๋ค. ์ด๋ ์ด๋ฏธ์ง ์ฒ๋ฆฌ, ๋ฐ์ดํฐ ๋ถ์ ๋๋ ๋ณต์กํ ๊ณ์ฐ๊ณผ ๊ฐ์ ๊ณ์ฐ ์ง์ฝ์ ์ธ ์์ ์ ํนํ ์ ์ฉํฉ๋๋ค. ์ด๋ฌํ ์์ ์ ์น ์์ปค๋ก ์คํ๋ก๋ํจ์ผ๋ก์จ ์ฌ์ฉ์ ์ธํฐํ์ด์ค์ ๋ฐ์์ฑ์ ์ ์งํ ์ ์์ต๋๋ค.
์์:
// main.js
const worker = new Worker('worker.js');
worker.onmessage = (event) => {
console.log('์์ปค๋ก๋ถํฐ์ ๊ฒฐ๊ณผ:', event.data);
};
worker.postMessage({ data: '์ฒ๋ฆฌ๋ฅผ ์ํ ๋ฐ์ดํฐ' });
// worker.js
self.onmessage = (event) => {
const data = event.data.data;
// ๊ณ์ฐ ์ง์ฝ์ ์์
์ํ
const result = processData(data);
self.postMessage(result);
};
function processData(data) {
// ... ์ฒ๋ฆฌ ๋ก์ง
return '์ฒ๋ฆฌ๋ ๋ฐ์ดํฐ';
}
6. ๋ชจ๋ ํ๋๋ ์ด์ (Module Federation)
Webpack 5์์ ์ฌ์ฉ ๊ฐ๋ฅํ ๋ชจ๋ ํ๋๋ ์ด์ ์ ๋ฐํ์์ ์๋ก ๋ค๋ฅธ ์ ํ๋ฆฌ์ผ์ด์ ๊ฐ์ ์ฝ๋๋ฅผ ๊ณต์ ํ ์ ์๊ฒ ํด์ค๋๋ค. ์ด๋ฅผ ํตํด ๋ง์ดํฌ๋ก ํ๋ก ํธ์๋๋ฅผ ๊ตฌ์ถํ๊ณ ๋ค๋ฅธ ์ ํ๋ฆฌ์ผ์ด์ ์์ ๋ชจ๋์ ๋์ ์ผ๋ก ๋ก๋ํ์ฌ ์ ์ฒด ๋ฒ๋ค ํฌ๊ธฐ๋ฅผ ์ค์ด๊ณ ์ฑ๋ฅ์ ํฅ์์ํฌ ์ ์์ต๋๋ค.
์์:
`app1`๊ณผ `app2`๋ผ๋ ๋ ๊ฐ์ ์ ํ๋ฆฌ์ผ์ด์ ์ด ์๋ค๊ณ ๊ฐ์ ํด ๋ด ์๋ค. `app1`์ ๋ฒํผ ์ปดํฌ๋ํธ๋ฅผ `app2`์ ๊ณต์ ํ๊ณ ์ถ์ต๋๋ค.
app1 (webpack.config.js):
const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
// ... ๋ค๋ฅธ ์ค์ ๋ค
plugins: [
new ModuleFederationPlugin({
name: 'app1',
filename: 'remoteEntry.js',
exposes: {
'./Button': './src/Button.js'
}
})
]
};
app2 (webpack.config.js):
const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
// ... ๋ค๋ฅธ ์ค์ ๋ค
plugins: [
new ModuleFederationPlugin({
name: 'app2',
remotes: {
app1: 'app1@http://localhost:3000/remoteEntry.js'
}
})
]
};
`app2`์์ ์ด์ `app1`์ ๋ฒํผ ์ปดํฌ๋ํธ๋ฅผ ์ํฌํธํ์ฌ ์ฌ์ฉํ ์ ์์ต๋๋ค:
import Button from 'app1/Button';
์ฝ๋ ๋ถํ ์ ์ํ ๋๊ตฌ ๋ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
์ฌ๋ฌ ๋๊ตฌ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ํ๋ก์ ํธ์์ ์ฝ๋ ๋ถํ ์ ๊ตฌํํ๋ ๋ฐ ๋์์ ์ค ์ ์์ต๋๋ค:
- Webpack: ์ง์ ์ ๋ถํ , ๋์ ์ํฌํธ, ๋ฒค๋ ๋ถํ ๋ฑ ๋ค์ํ ์ฝ๋ ๋ถํ ๊ธฐ๋ฒ์ ์ง์ํ๋ ๊ฐ๋ ฅํ๊ณ ๋ค์ฌ๋ค๋ฅํ ๋ชจ๋ ๋ฒ๋ค๋ฌ์ ๋๋ค.
- Rollup: ํธ๋ฆฌ ์์ดํน์ ๋ฐ์ด๋๊ณ ๊ณ ๋๋ก ์ต์ ํ๋ ๋ฒ๋ค์ ์์ฑํ๋ ๋ชจ๋ ๋ฒ๋ค๋ฌ์ ๋๋ค.
- Parcel: ์ต์ํ์ ์ค์ ์ผ๋ก ์ฝ๋ ๋ถํ ์ ์๋์ผ๋ก ์ฒ๋ฆฌํ๋ ์ ๋ก ๊ตฌ์ฑ(zero-configuration) ๋ฒ๋ค๋ฌ์ ๋๋ค.
- React.lazy: ๋์ ์ํฌํธ๋ฅผ ์ฌ์ฉํ์ฌ ์ปดํฌ๋ํธ๋ฅผ ์ง์ฐ ๋ก๋ฉ(lazy-loading)ํ๊ธฐ ์ํ React ๋ด์ฅ API์ ๋๋ค.
- Loadable Components: React์์ ์ฝ๋ ๋ถํ ์ ์ํ ๊ณ ์ฐจ ์ปดํฌ๋ํธ(higher-order component)์ ๋๋ค.
์ฝ๋ ๋ถํ ์ ์ํ ๋ชจ๋ฒ ์ฌ๋ก
์ฝ๋ ๋ถํ ์ ํจ๊ณผ์ ์ผ๋ก ๊ตฌํํ๋ ค๋ฉด ๋ค์ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๊ณ ๋ คํ์ญ์์ค:
- ์ ํ๋ฆฌ์ผ์ด์ ๋ถ์: ํฐ ์ปดํฌ๋ํธ, ๋๋ฌผ๊ฒ ์ฌ์ฉ๋๋ ๊ธฐ๋ฅ ๋๋ ๋ผ์ฐํธ ๊ธฐ๋ฐ ๊ฒฝ๊ณ์ ์ด์ ์ ๋ง์ถฐ ์ฝ๋ ๋ถํ ์ด ๊ฐ์ฅ ํฐ ์ํฅ์ ๋ฏธ์น ์ ์๋ ์์ญ์ ์๋ณํ์ญ์์ค.
- ์ฑ๋ฅ ์์ฐ ์ค์ : ๋ชฉํ ๋ก๋ฉ ์๊ฐ์ด๋ ๋ฒ๋ค ํฌ๊ธฐ์ ๊ฐ์ ์น์ฌ์ดํธ์ ์ฑ๋ฅ ๋ชฉํ๋ฅผ ์ ์ํ๊ณ , ์ด ์์ฐ์ ์ฝ๋ ๋ถํ ๋ ธ๋ ฅ์ ์ง์นจ์ผ๋ก ์ฌ์ฉํ์ญ์์ค.
- ์ฑ๋ฅ ๋ชจ๋ํฐ๋ง: ์ฝ๋ ๋ถํ ์ ๊ตฌํํ ํ ์น์ฌ์ดํธ์ ์ฑ๋ฅ์ ์ถ์ ํ์ฌ ์ํ๋ ๊ฒฐ๊ณผ๋ฅผ ์ ๊ณตํ๋์ง ํ์ธํ์ญ์์ค. Google PageSpeed Insights, WebPageTest ๋๋ Lighthouse์ ๊ฐ์ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ฑ๋ฅ ์งํ๋ฅผ ์ธก์ ํ์ญ์์ค.
- ์บ์ฑ ์ต์ ํ: ์ฌ์ฉ์๊ฐ ์ฌ๋ฐฉ๋ฌธ ์ ์ฝ๋๋ฅผ ๋ค์ ๋ค์ด๋ก๋ํ ํ์๊ฐ ์๋๋ก ์๋ฐ์คํฌ๋ฆฝํธ ๋ฒ๋ค์ ์ ์ ํ๊ฒ ์บ์ํ๋๋ก ์๋ฒ๋ฅผ ๊ตฌ์ฑํ์ญ์์ค. ์บ์ ๋ฒ์คํ (cache-busting) ๊ธฐ๋ฒ(์: ํ์ผ ์ด๋ฆ์ ํด์ ์ถ๊ฐ)์ ์ฌ์ฉํ์ฌ ์ฌ์ฉ์๊ฐ ํญ์ ์ต์ ๋ฒ์ ์ ์ฝ๋๋ฅผ ๋ฐ๋๋ก ํ์ญ์์ค.
- ์ฝํ ์ธ ์ ์ก ๋คํธ์ํฌ(CDN) ์ฌ์ฉ: ์ ์ธ๊ณ ์ฌ์ฉ์์ ๋ก๋ฉ ์๊ฐ์ ๊ฐ์ ํ๊ธฐ ์ํด CDN์ ํตํด ์๋ฐ์คํฌ๋ฆฝํธ ๋ฒ๋ค์ ๋ฐฐํฌํ์ญ์์ค.
- ์ฌ์ฉ์ ์ธ๊ตฌ ํต๊ณ ๊ณ ๋ ค: ๋์ ๊ณ ๊ฐ์ ํน์ ์๊ตฌ์ ๋ง๊ฒ ์ฝ๋ ๋ถํ ์ ๋ต์ ์กฐ์ ํ์ญ์์ค. ์๋ฅผ ๋ค์ด, ์ฌ์ฉ์์ ์๋น ๋ถ๋ถ์ด ๋๋ฆฐ ์ธํฐ๋ท ์ฐ๊ฒฐ์ ์ฌ์ฉํ๋ค๋ฉด ์ฝ๋ ๋ถํ ์ ๋ ์ ๊ทน์ ์ผ๋ก ์ํํด์ผ ํ ์ ์์ต๋๋ค.
- ์๋ํ๋ ๋ฒ๋ค ๋ถ์: Webpack Bundle Analyzer์ ๊ฐ์ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฒ๋ค ํฌ๊ธฐ๋ฅผ ์๊ฐํํ๊ณ ์ต์ ํ ๊ธฐํ๋ฅผ ์๋ณํ์ญ์์ค.
์ค์ ์ฌ๋ก ๋ฐ ์ผ์ด์ค ์คํฐ๋
๋ง์ ๊ธฐ์ ๋ค์ด ์น์ฌ์ดํธ ์ฑ๋ฅ์ ๊ฐ์ ํ๊ธฐ ์ํด ์ฝ๋ ๋ถํ ์ ์ฑ๊ณต์ ์ผ๋ก ๊ตฌํํ์ต๋๋ค. ๋ช ๊ฐ์ง ์๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- Google: Google์ Gmail, Google ์ง๋ ๋ฑ ์์ฌ์ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฐ์ ๊ฑธ์ณ ์ฝ๋ ๋ถํ ์ ๊ด๋ฒ์ํ๊ฒ ์ฌ์ฉํ์ฌ ๋น ๋ฅด๊ณ ๋ฐ์์ฑ์ด ๋ฐ์ด๋ ์ฌ์ฉ์ ๊ฒฝํ์ ์ ๊ณตํฉ๋๋ค.
- Facebook: Facebook์ ๋ค์ํ ๊ธฐ๋ฅ๊ณผ ์ปดํฌ๋ํธ์ ๋ก๋ฉ์ ์ต์ ํํ๊ธฐ ์ํด ์ฝ๋ ๋ถํ ์ ํ์ฉํ์ฌ ์ฌ์ฉ์๊ฐ ํ์ํ ์ฝ๋๋ง ๋ค์ด๋ก๋ํ๋๋ก ๋ณด์ฅํฉ๋๋ค.
- Netflix: Netflix๋ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ์์ ์๊ฐ์ ๊ฐ์ ํ๊ธฐ ์ํด ์ฝ๋ ๋ถํ ์ ์ฌ์ฉํ์ฌ ์ฌ์ฉ์๊ฐ ๋ ๋นจ๋ฆฌ ์ฝํ ์ธ ์คํธ๋ฆฌ๋ฐ์ ์์ํ ์ ์๋๋ก ํฉ๋๋ค.
- ๋ํ ์ ์ ์๊ฑฐ๋ ํ๋ซํผ (Amazon, Alibaba): ์ด ํ๋ซํผ๋ค์ ์ฝ๋ ๋ถํ ์ ํ์ฉํ์ฌ ์ํ ํ์ด์ง ๋ก๋ฉ ์๊ฐ์ ์ต์ ํํ๊ณ , ์ ์ธ๊ณ ์๋ฐฑ๋ง ์ฌ์ฉ์์ ์ผํ ๊ฒฝํ์ ํฅ์์ํต๋๋ค. ์ฌ์ฉ์ ์ํธ์์ฉ์ ๋ฐ๋ผ ์ํ ์์ธ ์ ๋ณด, ๊ด๋ จ ์ํ, ์ฌ์ฉ์ ๋ฆฌ๋ทฐ๋ฅผ ๋์ ์ผ๋ก ๋ก๋ํฉ๋๋ค.
์ด๋ฌํ ์ฌ๋ก๋ค์ ์น์ฌ์ดํธ ์ฑ๋ฅ๊ณผ ์ฌ์ฉ์ ๊ฒฝํ์ ๊ฐ์ ํ๋ ๋ฐ ์ฝ๋ ๋ถํ ์ด ํจ๊ณผ์ ์์ ๋ณด์ฌ์ค๋๋ค. ์ฝ๋ ๋ถํ ์ ์์น์ ๋ค์ํ ์ง์ญ๊ณผ ์ธํฐ๋ท ์ ์ ์๋์ ๋ณดํธ์ ์ผ๋ก ์ ์ฉ ๊ฐ๋ฅํฉ๋๋ค. ์ธํฐ๋ท ์ฐ๊ฒฐ์ด ๋๋ฆฐ ์ง์ญ์์ ์ด์๋๋ ํ์ฌ๋ ๊ณต๊ฒฉ์ ์ธ ์ฝ๋ ๋ถํ ์ ๋ต์ ๊ตฌํํจ์ผ๋ก์จ ๊ฐ์ฅ ํฐ ์ฑ๋ฅ ํฅ์์ ๋ณผ ์ ์์ต๋๋ค.
๊ฒฐ๋ก
์ฝ๋ ๋ถํ ์ ์๋ฐ์คํฌ๋ฆฝํธ ๋ฒ๋ค์ ์ต์ ํํ๊ณ ์น์ฌ์ดํธ ์ฑ๋ฅ์ ํฅ์์ํค๋ ๋ฐ ์ค์ํ ๊ธฐ๋ฒ์ ๋๋ค. ์ ํ๋ฆฌ์ผ์ด์ ์ฝ๋๋ฅผ ๋ ์๊ณ ๊ด๋ฆฌํ๊ธฐ ์ฌ์ด ์ฒญํฌ๋ก ๋๋๋ฉด ์ด๊ธฐ ๋ก๋ฉ ์๊ฐ์ ์ค์ด๊ณ ์ฌ์ฉ์ ๊ฒฝํ์ ํฅ์์ํค๋ฉฐ ์บ์ฑ ํจ์จ์ฑ์ ๋์ผ ์ ์์ต๋๋ค. ๋ค์ํ ์ ํ์ ์ฝ๋ ๋ถํ ์ ์ดํดํ๊ณ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ์ฑํํจ์ผ๋ก์จ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฑ๋ฅ์ ํฌ๊ฒ ํฅ์์ํค๊ณ ์ฌ์ฉ์์๊ฒ ๋ ๋์ ๊ฒฝํ์ ์ ๊ณตํ ์ ์์ต๋๋ค.
์น ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ ์ ๋ ๋ณต์กํด์ง์ ๋ฐ๋ผ ์ฝ๋ ๋ถํ ์ ์ค์์ฑ์ ๋์ฑ ์ปค์ง ๊ฒ์ ๋๋ค. ์ต์ ์ฝ๋ ๋ถํ ๊ธฐ๋ฒ๊ณผ ๋๊ตฌ์ ๋ํ ์ต์ ์ ๋ณด๋ฅผ ์ ์งํจ์ผ๋ก์จ ์น์ฌ์ดํธ๊ฐ ์ฑ๋ฅ์ ์ต์ ํ๋๊ณ ์ ์ธ๊ณ์ ์ผ๋ก ์ํํ ์ฌ์ฉ์ ๊ฒฝํ์ ์ ๊ณตํ๋๋ก ๋ณด์ฅํ ์ ์์ต๋๋ค.